﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class AnimBase : MonoBehaviour {


    [SerializeField]
    protected AnimationCurve m_Curve = AnimationCurve.EaseInOut(0, 0, 1, 1);

    public void SetCurve(AnimationCurve _curve)
    {
        m_Curve = _curve;
    }

    List<Coroutine> m_CallBackCoroutines = new List<Coroutine>();

    protected Coroutine PlayAnim<T>(T targetValue, float time, Func<T, T, float, T> lerpFunc, Action<T> setCurValueAction, Func<T> getCurValueFunc, Action callback)
    {
        if (!this || !this.gameObject || !this.gameObject.activeInHierarchy)
            return null;

        var newCor = StartCoroutine(PlayAnimCoroutine(targetValue, time, lerpFunc, setCurValueAction, getCurValueFunc));

        if (callback != null)
        {
            m_CallBackCoroutines.Add(newCor);
        }

        DoActionDelay.DelayAction(time,()=>
        {
            if (callback != null)
            {
                if (newCor != null && m_CallBackCoroutines.Contains(newCor))
                {
                    callback.Invoke();
                    m_CallBackCoroutines.Remove(newCor);
                }
            }
        } );
        return newCor;
    }

    public void StopAnim(Coroutine coroutine)
    {
        var exist = m_CallBackCoroutines.Find(e => e != null && e == coroutine);
        if(exist != null)
        {
            m_CallBackCoroutines.Remove(exist);
            StopCoroutine(exist);
        }
        else
        {
            StopCoroutine(coroutine);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="targetValue"></param>
    /// <param name="time"></param>
    /// <param name="lerpFunc">Lerp函数</param>
    /// <param name="setCurValueAction"></param>
    /// <param name="getCurValueFunc"></param>
    /// <param name="callback"></param>
    /// <returns></returns>
    IEnumerator PlayAnimCoroutine<T>(T targetValue, float time, Func<T, T, float, T> lerpFunc, Action<T> setCurValueAction, Func<T> getCurValueFunc)
    {
        if (setCurValueAction == null || getCurValueFunc == null || lerpFunc == null)
            yield break;
        
        float timer = 0;
        T originalValue = getCurValueFunc();
        while (timer <= time)
        {
            timer += Time.deltaTime;

            float rate = timer / time;
            float y = m_Curve.Evaluate(rate);

            var curValue = lerpFunc(originalValue, targetValue, y);
            
            setCurValueAction(curValue);
            yield return null;
        }

    }

    public void StopAllAnim()
    {
        StopAllCoroutines();
    }

    private void OnDestroy()
    {
        StopAllAnim();
    }
}
